package com.shao.channelHandler.handler;

import com.shao.ServiceConfig;
import com.shao.SrpcBootstrap;
import com.shao.channelHandler.enums.ResponseCodeEnum;
import com.shao.transport.message.RequestPayload;
import com.shao.transport.message.SrpcRequest;
import com.shao.transport.message.SrpcResponse;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author PaoFu
 * @version 1.0
 * @data 2025/4/24 10:56
 */
@Slf4j
public class MethodCallHandler extends SimpleChannelInboundHandler<SrpcRequest> {
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, SrpcRequest srpcRequest) {
        // 获取载体
        RequestPayload requestPayLoad = srpcRequest.getRequestPayLoad();
        // 根据载体进行方法调用
        Object res = callTargetMethod(requestPayLoad);
        // 封装响应
        SrpcResponse srpcResponse = new SrpcResponse()
                .setRequestId(srpcRequest.getRequestId())
                .setResponseCode(ResponseCodeEnum.SUCCESS.getCode())
                .setCompressType(srpcRequest.getCompressType())
                .setSerializeType(srpcRequest.getSerializeType())
                .setBody(res);

        // 写出响应
        channelHandlerContext.channel().writeAndFlush(srpcResponse);
    }

    private Object callTargetMethod(RequestPayload requestPayLoad) {
        if (requestPayLoad == null) {
            return null;
        }
        String methodName = requestPayLoad.getMethodName();
        String interfaceName = requestPayLoad.getInterfaceName();
        Class<?>[] parametersType = requestPayLoad.getParametersType();
        Object[] parametersValue = requestPayLoad.getParametersValue();
        // 匹配暴露的具体实现
        ServiceConfig serviceConfig = SrpcBootstrap.SERVICE_LIST.get(interfaceName);
        Object refImpl = serviceConfig.getRef();
        Class<?> aClass = refImpl.getClass();
//        Method method = serviceConfig.getInterface().getMethod(methodName, parametersType);
        try {
            Method method = aClass.getMethod(methodName, parametersType);
            return method.invoke(refImpl, parametersValue);
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }
}
